package org.btik.light.server.dev.manage;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.btik.light.server.platform.common.api.bean.common.StatusResult;
import org.btik.light.server.platform.common.api.bean.login.LoginDto;
import org.btik.light.server.platform.common.api.bean.login.LoginResult;
import org.btik.light.server.platform.common.api.bean.user.User;
import org.btik.light.server.platform.common.api.bean.user.UserVo;
import org.btik.light.server.platform.common.api.dao.LightDao;
import org.btik.light.server.platform.common.api.service.LoginService;
import org.btik.light.tool.MDUtil;
import org.btik.light.tool.UuidUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;

import static org.btik.light.server.platform.common.api.bean.common.ResultFactory.failed;
import static org.btik.light.server.platform.common.api.bean.common.ResultFactory.success;
import static org.btik.light.server.platform.common.api.bean.login.LoginStatus.*;

/**
 * @author lustre
 * @since 2023/6/11 14:45
 */
@Service
public class LoginServiceImpl implements LoginService {

    private final Log log = LogFactory.getLog(LoginServiceImpl.class);

    @Autowired
    private LightDao lightDao;



    @Value("${user.login.lock-timeout}")
    private long lockTimeout;

    @Override
    public String token() {
        String uuidString = UuidUtil.uuidString(8);

        return uuidString;
    }

    @Override
    public StatusResult<LoginResult> login(String ip, String code, LoginDto loginDto) {
        if (!code.equalsIgnoreCase(loginDto.getCaptcha())) {
            return failed(CAPTCHA_FAILED);
        }
        String account = loginDto.getAccount();
        User user = lightDao.get(account, User.class);
        // 并不让对端知道用户名是否存在
        if (user == null) {
            log.warn("user not exists:[" + account + "]");
            return failed(PASSWORD_FAILED);
        }
        if (!user.getEnable()) {
            log.warn("user not enable:[" + account + "]");
            return failed(NO_PERMISSIONS);
        }
        if (isLocked(user)) {
            return failed(LOCKED);
        }
        String password = loginDto.getPassword();
        String digest = MDUtil.digestAsHex(MDUtil.Algorithm.SHA_512_256, account + password);
        if (!digest.equals(user.getPassword())) {
            return onPasswordFailed(user) ? failed(LOCKED) : failed(PASSWORD_FAILED);
        }
        LoginResult loginResult = new LoginResult();

        user.setLastLoginIp(ip);
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        loginResult.setUser(userVo);
        onLoginSuccess(user);
        return success(loginResult);
    }

    public void onLoginSuccess(User user) {
        user.setLockTime(0);
        user.setLocked(false);
        user.setFailedCount(0);
        Date date = new Date();
        user.setLastLoginTime(date);
        lightDao.save(user);
    }

    public boolean isLocked(User user) {
        return user.isLocked() && System.currentTimeMillis() < (user.getLockTime() + lockTimeout);
    }

    /**
     * @return 本次是否已锁定
     */
    public boolean onPasswordFailed(User user) {
        int failedCount = user.getFailedCount();
        user.setFailedCount(++failedCount);
        if (failedCount > 3) {
            user.setLockTime(System.currentTimeMillis());
            user.setLocked(true);
            lightDao.save(user);
            return true;
        }
        lightDao.save(user);

        return false;

    }

}
